package org.dromara.solonplugins.activerecord;

import javax.sql.DataSource;

import org.dromara.solonplugins.activerecord.annotation.Db;
import org.dromara.solonplugins.activerecord.integration.DbManager;
import org.noear.solon.Utils;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.Plugin;
import org.noear.solon.core.VarHolder;

import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.Config;
import com.jfinal.plugin.activerecord.DbKit;
import com.jfinal.plugin.activerecord.DbPro;


/**
 * Solon-jfinal activerecord orm插件入口 参考文档{@link https://jfinal.com/doc/5-15}
 * 
 * @author: xls-web (小xu中年)
 */
public class XPluginImp implements Plugin {
	
	@Override
    public void start(AppContext context) throws Throwable {
		//监听事件
        context.subWrapsOfType(DataSource.class, bw->{
        	DbManager.reg(bw);
        });
        
        context.beanBuilderAdd(Db.class, (clz, wrap, anno) -> {
            builderAddDo(clz, wrap, anno.value());
        });

        context.beanInjectorAdd(Db.class, (varH, anno) -> {
            injectorAddDo(varH, anno.value());
        });
        
    }
	
	private void builderAddDo(Class<?> clz, BeanWrap wrap, String annoValue) {
        if (clz.isInterface() == false) {
            return;
        }

        if (Utils.isEmpty(annoValue)) {
            wrap.context().getWrapAsync(DataSource.class, (dsBw) -> {
                create0(clz, dsBw);
            });
        } else {
            wrap.context().getWrapAsync(annoValue, (dsBw) -> {
                if (dsBw.raw() instanceof DataSource) {
                    create0(clz, dsBw);
                }
            });
        }
    }
	
    private void injectorAddDo(VarHolder varH, String annoValue) {
        if (Utils.isEmpty(annoValue)) {
            varH.context().getWrapAsync(DataSource.class, (dsBw) -> {
                inject0(varH, dsBw, annoValue);
            });
        } else {
            varH.context().getWrapAsync(annoValue, (dsBw) -> {
                if (dsBw.raw() instanceof DataSource) {
                    inject0(varH, dsBw, annoValue);
                }
            });
        }
    }
    
    /**
     * 字段注入
     */
    private void inject0(VarHolder varH, BeanWrap dsBw, String annoValue) {
    	//如果是 DbPro 或者 Db
    	Class<?> varClz = varH.getType();
        if (DbPro.class.isAssignableFrom(varClz)) {
            if (Utils.isEmpty(annoValue)) {
            	annoValue = DbKit.MAIN_CONFIG_NAME;
            }

            Config config = DbKit.getConfig(annoValue);
            if (config == null) {
            	DbManager.reg(dsBw);
            }
            varH.setValue(com.jfinal.plugin.activerecord.Db.use(annoValue));
            return;
        }
        //如果是 ActiveRecordPlugin
        if (IPlugin.class.isAssignableFrom(varH.getType())) {
            IPlugin arp = DbManager.get(dsBw);
            varH.setValue(arp);
            return;
        }
    }
	
    private void create0(Class<?> clz, BeanWrap dsBw) {
        Object raw = DbManager.get(dsBw);

        if (raw != null) {
            dsBw.context().wrapAndPut(clz, raw);
        }else {
        	DbManager.reg(dsBw);
        }
    }


	@Override
    public void prestop() throws Throwable {
        // 循环停止ActiveRecordPlugin
		DbManager.stop();
    }
	
	@Override
	public void stop() throws Throwable {
		Plugin.super.stop();
		DbManager.clear();
	}
}
